package managers;

import java.io.IOException;

import messages.observer.EventCollectionMessage;

import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;

import state.group.events.EventCollection;
import state.group.events.EventType;
import test.BaseTest;
import test.stubs.ElevatorStub;
import test.stubs.ObserverStub;

import static org.junit.Assert.*;

public class ElevatorTest extends BaseTest {

    @BeforeClass
    public static void initSystem() throws IOException
    {
        BaseTest.initSystem();
        
        //shut down the other threads, so that only the Observer Thread is running.
        HallCallManager.shutdown();
    }
    
    @AfterClass
    public static void teardownSystem() throws IOException
    {
        BaseTest.teardownSystem();
    }
    
    private ElevatorStub stub;
    
    @Before
    public void setup() throws IOException
    {
        stub = new ElevatorStub();
        stub.startUp(port);
        stub.start();
    }
    
    @After
    public void cleanUp() throws InterruptedException
    {
        //nothing yet
    	
    	Thread.sleep(1000);
    }
    
    @Test
    public void testDeregister() throws InterruptedException, IOException
    {
        Thread.sleep(5000);
        
        stub.waitForDeregistration();
        
        stub.deregister();
        
        Thread.sleep(1000);
    }
    
    @Test
    public void testMultipleElevators() throws IOException, InterruptedException
    {
    	ElevatorStub stub1 = new ElevatorStub();
    	stub1.startUp(port);
    	stub1.start();
    	
    	ElevatorStub stub2 = new ElevatorStub();
    	stub2.startUp(port);
    	stub2.start();
    	
    	ObserverStub obs = new ObserverStub();
    	obs.connect(port);
    	
    	EventCollectionMessage regs = (EventCollectionMessage) obs.readObserver();
    	EventCollection coll = regs.getEvents();
    	
    	assertEquals(3, coll.size());
    	assertEquals(EventType.RegistrationEvent, coll.get(0).getEventType());
    	assertEquals(EventType.RegistrationEvent, coll.get(1).getEventType());
    	assertEquals(EventType.RegistrationEvent, coll.get(2).getEventType());
    	
    	Thread.sleep(2000);
    	
    	stub.struct.lastKnownFloor = 4;
    	stub1.struct.lastKnownFloor = 6;
    	stub2.struct.lastKnownFloor = 8;
    	
    	EventCollectionMessage mess = (EventCollectionMessage) obs.readObserver();
     	coll = mess.getEvents();
    	
    	assertEquals(3, coll.size());
    	assertEquals(EventType.FloorEvent, coll.get(0).getEventType());
    	assertEquals(EventType.FloorEvent, coll.get(1).getEventType());
    	assertEquals(EventType.FloorEvent, coll.get(2).getEventType());
    	
    	obs.close();
    	
    	stub2.deregister();
    	stub1.deregister();
    	stub.deregister();
    	
    }
    
    @Test
    public void testUnExpectedShutdown() throws InterruptedException
    {
    	Thread.sleep(2000);
    	
    	ElevatorManager.shutdown();
    }

}
